;-------------------------------------------------------------------------------
format ELF64 executable 3
entry start

SDL_INIT_TIMER = 0x00000001
SDL_INIT_VIDEO = 0x00000020
SDL_GL_RED_SIZE = 0
SDL_GL_GREEN_SIZE = 1
SDL_GL_BLUE_SIZE = 2
SDL_GL_DOUBLEBUFFER = 5
SDL_WINDOW_OPENGL = 0x00000002
SDL_WINDOW_SHOWN = 0x00000004
SDL_WINDOW_BORDERLESS = 0x00000010
SDL_KEYDOWN = 0x300
AUDIO_S16LSB = 0x8010

GL_VERTEX_SHADER = 0x8B31
GL_FRAGMENT_SHADER = 0x8B30

WIN_X = 10
WIN_Y = 10
WIN_W = 1024
WIN_H = 768

DEBUG = 1

macro emit [param] { param }
;-------------------------------------------------------------------------------
include 'import64.inc'
interpreter '/lib64/ld-linux-x86-64.so.2'
needed 'libdl.so.2'
import dlopen,dlsym
;-------------------------------------------------------------------------------
segment readable executable

audio_callback:
    sub rsp,8
    emit <mov rdi,g_str_SDL_PauseAudio>,<call [printf]>
    add rsp,8
    ret

start:
    mov rbp,rsp
    sub rsp,256
    ; define local variables
    emit\
        <libsdl equ rbp-8>,<libc equ rbp-16>,\
        <SDL_PollEvent equ rbp-24>,<SDL_GL_SwapWindow equ rbp-32>,\
        <win equ rbp-48>,<event equ rbp-176>,<audio_spec equ rbp-208>
if DEBUG = 1
    ; load libc
    emit <mov rdi,g_str_libc>,<xor esi,esi>,<inc esi>,<call [dlopen]>,<mov [libc],rax>
    emit <mov rdi,[libc]>,<mov rsi,g_str_printf>,<call [dlsym]>,<mov [printf],rax>
end if
    ; load libSDL-1.3.so.0
    emit <mov rdi,g_str_libsdl>,<xor esi,esi>,<inc esi>,<call [dlopen]>,<mov [libsdl],rax>
    ; SDL_Init
    emit <mov rdi,[libsdl]>,<mov rsi,g_str_SDL_Init>,<call [dlsym]>
    emit <mov edi,SDL_INIT_TIMER+SDL_INIT_VIDEO>,<call rax>
    ; create window
    emit <mov rdi,[libsdl]>,<mov rsi,g_str_SDL_CreateWindow>,<call [dlsym]>
    emit <mov rdi,g_str_SDL_CreateWindow>,<mov esi,WIN_X>,<mov edx,WIN_Y>,<mov ecx,WIN_W>,<mov r8d,WIN_H>,\
        <mov r9d,SDL_WINDOW_SHOWN+SDL_WINDOW_OPENGL+SDL_WINDOW_BORDERLESS>,<call rax>,<mov [win],rax>
    ; create context
    emit <mov rdi,[libsdl]>,<mov rsi,g_str_SDL_GL_CreateContext>,<call [dlsym]>
    emit <mov rdi,[win]>,<call rax>
    ; load needed SDL functions
    emit <mov rdi,[libsdl]>,<mov rsi,g_str_SDL_PollEvent>,<call [dlsym]>,<mov [SDL_PollEvent],rax>
    emit <mov rdi,[libsdl]>,<mov rsi,g_str_SDL_GL_SwapWindow>,<call [dlsym]>,<mov [SDL_GL_SwapWindow],rax>
    ; open audio device
    mov dword [audio_spec+0],44100 ; freq
    mov word [audio_spec+4],AUDIO_S16LSB ; format
    mov byte [audio_spec+6],1 ; channel
    mov word [audio_spec+8],2048 ; samples
    mov rax,audio_callback
    mov qword [audio_spec+16],rax ; callback
    mov qword [audio_spec+24],0 ; userdata
    emit <mov rdi,[libsdl]>,<mov rsi,g_str_SDL_OpenAudio>,<call [dlsym]>
    emit <lea rdi,[audio_spec]>,<xor esi,esi>,<call rax>
    emit <mov rdi,g_str_d>,<mov esi,eax>,<call [printf]>
    ; start audio device
    emit <mov rdi,[libsdl]>,<mov rsi,g_str_SDL_PauseAudio>,<call [dlsym]>
    emit <xor edi,edi>,<call rax>
    ; enter main loop
      .main_loop:
    ; get window event
    emit <lea rdi,[event]>,<call qword [SDL_PollEvent]>
    cmp dword [event+0],SDL_KEYDOWN
    je .main_loop_end
    ; swap
    emit <mov rdi,[win]>,<call qword [SDL_GL_SwapWindow]>
    jmp .main_loop
      .main_loop_end:
    ; close audio device
    emit <mov rdi,[libsdl]>,<mov rsi,g_str_SDL_CloseAudio>,<call [dlsym]>,<call rax>
    ; terminate process
    emit <mov rdi,[libsdl]>,<mov rsi,g_str_SDL_Quit>,<call [dlsym]>,<call rax>
    emit <mov eax,60>,<xor edi,edi>,syscall
;-------------------------------------------------------------------------------
segment readable writeable

g_str_SDL_Init db 'SDL_Init',0
g_str_SDL_Quit db 'SDL_Quit',0
g_str_SDL_CreateWindow db 'SDL_CreateWindow',0
g_str_SDL_PollEvent db 'SDL_PollEvent',0
g_str_SDL_GL_CreateContext db 'SDL_GL_CreateContext',0
g_str_SDL_GL_SwapWindow db 'SDL_GL_SwapWindow',0
g_str_libsdl db 'libSDL-1.3.so.0',0
g_str_SDL_OpenAudio db 'SDL_OpenAudio',0
g_str_SDL_PauseAudio db 'SDL_PauseAudio',0
g_str_SDL_CloseAudio db 'SDL_CloseAudio',0
if DEBUG = 1
printf dq 0
g_str_libc db 'libc.so.6',0
g_str_printf db 'printf',0
g_str_d db '%d',10,0
end if
;-------------------------------------------------------------------------------
